using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace DSBarCode
{
  public class BarCodeCtrl:Control
  {
    private System.Windows.Forms.Panel BarCodePanel;
    private System.Drawing.Printing.PrintDocument printDocument1;
    private System.ComponentModel.Container components=null;

    public enum AlignType
    {
      Left,
      Center,
      Right
    }

    public enum BarCodeWeight
    {
      Small=1,
      Medium,
      Large
    }

    private AlignType align=AlignType.Center;
    private String code="1234567890";
    private int leftMargin=10;
    private int topMargin=10;
    private int height=50;
    private bool showHeader;
    private bool showFooter;
    private String headerText="BarCode Demo";
    private BarCodeWeight weight=BarCodeWeight.Small;
    private Font headerFont=new Font("Courier",18);
    private Font footerFont=new Font("Courier",8);
    private double wideToNarrowRatio=3;
    [Category("BarCode")]
    public double BarWideToNarrowRatio
    {
      get { return wideToNarrowRatio; }
      set { wideToNarrowRatio=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public AlignType BarVertAlign
    {
      get { return align; }
      set { align=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public String BarCode
    {
      get { return code; }
      set { code=value.ToUpper(); BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public int BarCodeHeight
    {
      get { return height; }
      set { height=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public int BarLeftMargin
    {
      get { return leftMargin; }
      set { leftMargin=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public int BarTopMargin
    {
      get { return topMargin; }
      set { topMargin=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public bool BarShowHeader
    {
      get { return showHeader; }
      set { showHeader=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public bool BarShowFooter
    {
      get { return showFooter; }
      set { showFooter=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public String BarHeaderText
    {
      get { return headerText; }
      set { headerText=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public BarCodeWeight BarWeight
    {
      get { return weight; }
      set { weight=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public Font BarHeaderFont
    {
      get { return headerFont; }
      set { headerFont=value; BarCodePanel.Invalidate(); }
    }
    [Category("BarCode")]
    public Font BarFooterFont
    {
      get { return footerFont; }
      set { footerFont=value; BarCodePanel.Invalidate(); }
    }

    public BarCodeCtrl()
    {
      InitializeComponent();
    }

    public void Print()
    {
      PrintDialog pd=new PrintDialog();
      pd.Document=printDocument1;

      if(pd.ShowDialog()==DialogResult.OK)
      {
        pd.Document.Print();
      }
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose(bool disposing)
    {
      if(disposing)
      {
        if(components!=null)
          components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Component Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.BarCodePanel=new System.Windows.Forms.Panel();
      this.printDocument1=new System.Drawing.Printing.PrintDocument();
      this.SuspendLayout();
      // 
      // BarCodePanel
      // 
      this.BarCodePanel.BackColor=System.Drawing.SystemColors.Window;
      this.BarCodePanel.Dock=System.Windows.Forms.DockStyle.Fill;
      this.BarCodePanel.Location=new System.Drawing.Point(0,0);
      this.BarCodePanel.Name="BarCodePanel";
      this.BarCodePanel.Size=new System.Drawing.Size(424,240);
      this.BarCodePanel.TabIndex=0;
      this.BarCodePanel.Paint+=new System.Windows.Forms.PaintEventHandler(this.panel1_Paint);
      // 
      // printDocument1
      // 
      this.printDocument1.PrintPage+=new System.Drawing.Printing.PrintPageEventHandler(this.printDocument1_PrintPage);
      // 
      // BarCodeCtrl
      // 
      this.Controls.Add(this.BarCodePanel);
      this.Size=new System.Drawing.Size(424,240);
      this.MouseMove+=new System.Windows.Forms.MouseEventHandler(this.BarCodeCtrl_MouseMove);
      this.Resize+=new System.EventHandler(this.BarCodeCtrl_Resize);
      this.ResumeLayout(false);

    }
    #endregion

    String alphabet39="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";

    String[] coded39Char= 
		{
			/* 0 */ "000110100", 
			/* 1 */ "100100001", 
			/* 2 */ "001100001", 
			/* 3 */ "101100000",
			/* 4 */ "000110001", 
			/* 5 */ "100110000", 
			/* 6 */ "001110000", 
			/* 7 */ "000100101",
			/* 8 */ "100100100", 
			/* 9 */ "001100100", 
			/* A */ "100001001", 
			/* B */ "001001001",
			/* C */ "101001000", 
			/* D */ "000011001", 
			/* E */ "100011000", 
			/* F */ "001011000",
			/* G */ "000001101", 
			/* H */ "100001100", 
			/* I */ "001001100", 
			/* J */ "000011100",
			/* K */ "100000011", 
			/* L */ "001000011", 
			/* M */ "101000010", 
			/* N */ "000010011",
			/* O */ "100010010", 
			/* P */ "001010010", 
			/* Q */ "000000111", 
			/* R */ "100000110",
			/* S */ "001000110", 
			/* T */ "000010110", 
			/* U */ "110000001", 
			/* V */ "011000001",
			/* W */ "111000000", 
			/* X */ "010010001", 
			/* Y */ "110010000", 
			/* Z */ "011010000",
			/* - */ "010000101", 
			/* . */ "110000100", 
			/*' '*/ "011000100",
			/* $ */ "010101000",
			/* / */ "010100010", 
			/* + */ "010001010", 
			/* % */ "000101010", 
			/* * */ "010010100" 
		};


    public void Paint(Graphics g)
    {
      String intercharacterGap="0";
      String str='*'+code.ToUpper()+'*';
      int strLength=str.Length;

      for(int i=0;i<code.Length;i++)
      {
        if(alphabet39.IndexOf(code[i])==-1||code[i]=='*')
        {
          g.DrawString("INVALID BAR CODE TEXT",Font,Brushes.Red,10,10);
          return;
        }
      }

      String encodedString="";

      for(int i=0;i<strLength;i++)
      {
        if(i>0)
          encodedString+=intercharacterGap;

        encodedString+=coded39Char[alphabet39.IndexOf(str[i])];
      }

      int encodedStringLength=encodedString.Length;
      int widthOfBarCodeString=0;



      if(align!=AlignType.Left)
      {
        for(int i=0;i<encodedStringLength;i++)
        {
          if(encodedString[i]=='1')
            widthOfBarCodeString+=(int)(wideToNarrowRatio*(int)weight);
          else
            widthOfBarCodeString+=(int)weight;
        }
      }

      int x=0;
      int wid=0;
      int yTop=0;
      SizeF hSize=g.MeasureString(headerText,headerFont);
      SizeF fSize=g.MeasureString(code,footerFont);

      int headerX=0;
      int footerX=0;

      if(align==AlignType.Left)
      {
        x=leftMargin;
        headerX=leftMargin;
        footerX=leftMargin;
      }
      else if(align==AlignType.Center)
      {
        x=(Width-widthOfBarCodeString)/2;
        headerX=(Width-(int)hSize.Width)/2;
        footerX=(Width-(int)fSize.Width)/2;
      }
      else
      {
        x=Width-widthOfBarCodeString-leftMargin;
        headerX=Width-(int)hSize.Width-leftMargin;
        footerX=Width-(int)fSize.Width-leftMargin;
      }

      if(showHeader)
      {
        yTop=(int)hSize.Height+topMargin;
        g.DrawString(headerText,headerFont,Brushes.Black,headerX,topMargin);
      }
      else
      {
        yTop=topMargin;
      }

      for(int i=0;i<encodedStringLength;i++)
      {
        if(encodedString[i]=='1')
          wid=(int)(wideToNarrowRatio*(int)weight);
        else
          wid=(int)weight;

        g.FillRectangle(i%2==0?Brushes.Black:Brushes.White,x,yTop,wid,height);

        x+=wid;
      }

      yTop+=height;

      if(showFooter)
        g.DrawString(code,footerFont,Brushes.Black,footerX,yTop);
    }
    public void panel1_Paint(object sender,System.Windows.Forms.PaintEventArgs e)
    {
      Paint(e.Graphics);

    }

    public void printDocument1_PrintPage(object sender,System.Drawing.Printing.PrintPageEventArgs e)
    {

      panel1_Paint(sender,new PaintEventArgs(e.Graphics,this.ClientRectangle));

    }

    public void SaveImage(String file)
    {
      Bitmap png=new Bitmap(Width,Height,System.Drawing.Imaging.PixelFormat.Format32bppArgb);

      Graphics g=Graphics.FromImage(png);
      g.FillRectangle(Brushes.White,0,0,Width,Height);

      panel1_Paint(null,new PaintEventArgs(g,this.ClientRectangle));

      png.Save(file,ImageFormat.Tiff);
    }

    private void BarCodeCtrl_Resize(object sender,System.EventArgs e)
    {
      BarCodePanel.Invalidate();
    }

    private void BarCodeCtrl_MouseMove(object sender,MouseEventArgs e)
    {
      if(e.Button==MouseButtons.Left)
      {


      }
    }
  }
}
